import { CONFIG, getApiBaseUrl, getTerminal, geTenantId } from './config'
import { useUserInfoStore } from '@/stores'

interface RequestOptions {
  url: string
  method: 'GET' | 'POST' | 'PUT' | 'DELETE'
  data?: any
  params?: Record<string, any>
  header?: Record<string, any>
  timeout?: number
  retry?: number
  retryDelay?: number
  loading?: boolean
}

interface ResponseData<T> {
  code: number
  data: T
  msg: string
}

// 获取当前环境的API基础路径
const BASE_URL = getApiBaseUrl()
console.log(`当前API基础路径:`, BASE_URL)

// 处理URL，确保不会出现双斜杠
const formatUrl = (baseUrl: string, path: string): string => {
  const cleanPath = path.replace(/^\/+/, '')
  return `${baseUrl}/${cleanPath}`
}

// 基础请求配置
const baseRequestConfig = {
  header: {
    'content-type': 'application/json',
    // 'x-platform': getPlatform(),
    'uni-app': 'true',
    'Tenant-id': geTenantId(),
    Terminal: getTerminal(),
  } as Record<string, string | number>,
}

// 添加请求拦截器
uni.addInterceptor('request', {
  invoke(args) {
    if (!args.header) {
      args.header = {}
    }

    // 合并基础配置
    args.header = {
      ...baseRequestConfig.header,
      ...args.header,
    }

    // 获取token并添加到请求头
    const userInfoStore = useUserInfoStore()
    const token = userInfoStore.getToken()
    if (token) {
      args.header['Authorization'] = `Bearer ${token}`
    }

    // 处理文本文件请求
    if (args.url.includes('/downloads/')) {
      args.responseType = 'text'
      args.header = {
        ...args.header,
        Accept: 'text/plain',
        'Content-Type': 'text/plain',
      }

      // #ifdef MP-WEIXIN
      // 微信小程序环境优化
      args.enableHttp2 = true
      args.enableQuic = true
      args.enableCache = true
      // #endif
    }

    return args
  },
  fail(err) {
    console.error('请求失败:', err)
    uni.showToast({
      title: '网络请求失败',
      icon: 'none',
    })
    return err
  },
})

// 添加响应拦截器
uni.addInterceptor('request', {
  success(args) {
    const { statusCode, data } = args

    // 处理授权错误
    if (statusCode === 401 || (data && data.code === 401)) {
      console.error('授权失败，需要重新登录')

      // 清除token和用户信息
      uni.removeStorageSync('token')
      uni.removeStorageSync('userInfo')

      // 显示提示
      uni.showToast({
        title: '登录已过期，请重新登录',
        icon: 'none',
        duration: 2000,
      })

      // 延迟跳转到登录页
      setTimeout(() => {
        uni.navigateTo({
          url: '/pages/login/index',
        })
      }, 1000)
    }

    return args
  },
})

class RequestManager {
  private static instance: RequestManager

  private constructor() {}

  public static getInstance(): RequestManager {
    if (!RequestManager.instance) {
      RequestManager.instance = new RequestManager()
    }
    return RequestManager.instance
  }

  public async get<T>(
    url: string,
    params?: Record<string, any>,
    options: Partial<RequestOptions> = {},
  ): Promise<ResponseData<T>> {
    return this.request<T>({
      url,
      method: 'GET',
      params,
      ...options,
    })
  }

  public async post<T>(
    url: string,
    data?: any,
    options: Partial<RequestOptions> = {},
  ): Promise<ResponseData<T>> {
    return this.request<T>({
      url,
      method: 'POST',
      data,
      ...options,
    })
  }

  public async request<T>(options: RequestOptions): Promise<ResponseData<T>> {
    const {
      url,
      method = 'GET',
      data,
      params,
      loading = true,
      retry = CONFIG.MAX_RETRY,
      retryDelay = CONFIG.RETRY_DELAY,
      timeout = CONFIG.TIMEOUT,
      ...rest
    } = options

    let retryCount = 0

    if (loading) {
      uni.showLoading({ title: '加载中...' })
    }

    const doRequest = async (): Promise<ResponseData<T>> => {
      try {
        // 使用formatUrl处理URL
        let requestUrl = url.startsWith('http') ? url : formatUrl(BASE_URL, url)

        // 处理params参数
        if (params) {
          const queryString = Object.entries(params)
            .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
            .join('&')
          requestUrl += (requestUrl.includes('?') ? '&' : '?') + queryString
        }

        console.log('Request URL:', requestUrl)

        // 获取最新的token
        const userInfoStore = useUserInfoStore()
        const token = userInfoStore.getToken()
        // 准备请求头
        const headers = {
          ...baseRequestConfig.header,
          ...(rest.header || {}),
        }

        // 如果有token则添加到请求头
        if (token) {
          headers['Authorization'] = `Bearer ${token}`
        }

        const response = await uni.request({
          url: requestUrl,
          method,
          data,
          timeout,
          header: headers,
          ...rest,
        })

        console.log('Response:', response)

        const responseData = response.data as ResponseData<T>

        if (response.statusCode !== 200) {
          throw new Error(responseData.message || '请求失败')
        }

        return responseData
      } catch (error: any) {
        console.error('Request error:', error)
        if (retryCount < retry) {
          retryCount++
          await new Promise((resolve) => setTimeout(resolve, retryDelay))
          return doRequest()
        }
        throw error
      }
    }

    try {
      const result = await doRequest()
      if (loading) {
        uni.hideLoading()
      }
      return result
    } catch (error: any) {
      if (loading) {
        uni.hideLoading()
      }
      uni.showToast({
        title: error.message || '网络错误',
        icon: 'none',
      })
      throw error
    }
  }

  public put<T>(
    url: string,
    data?: any,
    options: Omit<RequestOptions, 'url' | 'method' | 'data'> = {},
  ) {
    return this.request<T>({ ...options, url, method: 'PUT', data })
  }

  public delete<T>(url: string, options: Omit<RequestOptions, 'url' | 'method'> = {}) {
    return this.request<T>({ ...options, url, method: 'DELETE' })
  }
}

// 导出RequestManager类型
export type { RequestOptions, ResponseData }

// 导出request实例
const requestInstance = RequestManager.getInstance()

// 导出类型安全的request函数
export const request = {
  get: <T>(url: string, options: Omit<RequestOptions, 'url' | 'method'> = {}) =>
    requestInstance.request<T>({ ...options, url, method: 'GET' }),

  post: <T>(
    url: string,
    data?: any,
    options: Omit<RequestOptions, 'url' | 'method' | 'data'> = {},
  ) => requestInstance.request<T>({ ...options, url, method: 'POST', data }),

  put: <T>(
    url: string,
    data?: any,
    options: Omit<RequestOptions, 'url' | 'method' | 'data'> = {},
  ) => requestInstance.request<T>({ ...options, url, method: 'PUT', data }),

  delete: <T>(url: string, options: Omit<RequestOptions, 'url' | 'method'> = {}) =>
    requestInstance.request<T>({ ...options, url, method: 'DELETE' }),

  request: <T>(options: RequestOptions) => requestInstance.request<T>(options),
}

export { BASE_URL }
